﻿using System;
using System.Collections.Generic;
using System.Linq;
using Atmk.WaterMeter.MIS.Commons;
using Atmk.WaterMeter.MIS.Commons.Interfaces;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Logic;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Repository;
using Atmk.WaterMeter.MIS.Commons.Utils;
using Atmk.WaterMeter.MIS.Entities;
using Atmk.WaterMeter.MIS.Entities.Enums;
using Atmk.WaterMeter.MIS.Entities.Models;

namespace Atmk.WaterMeter.MIS.Logic
{
    /// <summary>
    /// 阶梯价格费用
    /// </summary>
    public class PriceStepLogic:IPriceStepLogic
    {
        private static readonly NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();


        private readonly IRepository _repository;
        private readonly ISystemParamentsLogic _systemParamentsLogic;
        private readonly IStepTariffRepository _stepTariffRepository;


        public PriceStepLogic(
            IRepository repository,
            ISystemParamentsLogic systemParamentsLogic,
            IStepTariffRepository stepTariffRepository
        )
        {
            _repository = repository;
            _systemParamentsLogic = systemParamentsLogic;
            _stepTariffRepository = stepTariffRepository;
        }

        /// <summary>
        /// 获取指定水表类型和价格名称下的价格
        /// </summary>
        /// <param name="meterType"></param>
        /// <param name="priceType"></param>
        /// <returns></returns>
        public List<double> GetPriceList(string meterType, string priceType)
        {
            var result = new List<double>();
            var tryParse = Enum.TryParse(meterType, out MeterType meterTypeEnum);
            if(!tryParse)
                return new List<double>();
            //获取价格分界点信息集合
            var prices = Enumerable.Where<PrcieStep>(_repository.FindAll<PrcieStep>(),
                p => p.MeterType == (int)meterTypeEnum && p.Name == priceType).ToList();
            if (prices.Count > 0)
            {
                //获取所有价格费用集合
                var fees = Enumerable.Where<PrcieStepFee>(_repository.FindAll<PrcieStepFee>(),
                    f => f.PiceStepId == prices[0].Id.ToString()).ToList();
                if (fees.Count > 0)
                {
                    var price1 = fees.Sum(f => f.Price1); //单价1
                    var price2 = fees.Sum(f => f.Price2); //单价2
                    var price3 = fees.Sum(f => f.Price3); //单价3
                    result.Add(price1);
                    result.Add(price2);
                    result.Add(price3);
                }
            }
            return result;
        }

        /// <summary>
        /// 查询所有价格及费用情况
        /// </summary>
        /// <returns></returns>
        public object SelectPriceFee(string projectId,string meterType = "")
        {
            try
            {
                var meterList = _systemParamentsLogic.MeterTypeGet(projectId);

                //获取价格分界点信息集合
                var prices = PrcieSteps(projectId, meterType);

                //获取所有价格费用集合--首个查询项目
                var fees = _stepTariffRepository.GetPrcieStepFeeList(prices.ToArray());
                //赋值
                var priceList = new object[prices.Count()];
                for (var i = 0; i < prices.Count(); i++)
                {
                    var pricelist = fees.Where(f => f.PiceStepId == prices[i].Id.ToString()).ToList();
                    priceList[i] = new
                    {
                        id = prices[i].Id.ToString(),
                        index = i + 1, //显示序号
                        meterType = MeterTypeSwitch(prices[i].MeterType),
                        title = prices[i].Name, //价格名称
                        price1 = pricelist.Sum(f => f.Price1).ToString("##.###"), //单价1
                        price2 = pricelist.Sum(f => f.Price2).ToString("##.###"), //单价2
                        price3 = pricelist.Sum(f => f.Price3).ToString("##.###"), //单价3
                        separation1 = prices[i].CutPoint1, //分界点1
                        separation2 = prices[i].CutPoint2, //分界点2
                        unit = PriceUnitSwitch(prices[i].PriceUnit), //单位
                        remark = prices[i].Memo
                    };
                }
                var feeList = new object[fees.Count];
                for (var i = 0; i < fees.Count; i++)
                {
                    feeList[i] = new
                    {
                        id = fees[i].Id.ToString(),
                        priceId = fees[i].PiceStepId, //guid字符串
                        index = i + 1, //显示序号
                        title = fees[i].Name, //费用名称
                        price1 = fees[i].Price1, //单价1
                        price2 = fees[i].Price2, //单价2
                        price3 = fees[i].Price3, //单价3
                        remark = fees[i].Memo
                    };
                }
                var result = new
                {
                    meterList,
                    priceList,
                    feeList
                };
                var resultType = new
                {
                    priceList,
                    feeList
                };
                if (meterType.Length > 0)
                    return resultType;
                return result;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                return null;
            }
        }
        public static string MeterTypeSwitch(int? value)
        {
            switch (value)
            {
                case 0: return "冷水水表";
                case 1: return "生活热水水表";
                case 2: return "直饮水水表";
                case 3: return "中水水表";
                case 4: return "FS型大水表";
                default: return "";
            }
        }
        public static string PriceUnitSwitch(int? value)
        {
            switch (value)
            {
                case 0: return "元/方";
                case 1: return "元/升";
                default: return "";
            }
        }
        /// <summary>
        /// 获取价格分界点信息集合
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="meterType"></param>
        /// <returns></returns>
        private List<PrcieStep> PrcieSteps(string projectId, string meterType="")
        {
            var prices = _stepTariffRepository.GetPrcieStepList(projectId);
            if (meterType == "") return prices;
            var tryParse = EnumHelper.TryEnumByDescription(meterType, out MeterType meterTypeEnum);
            if (tryParse)
                prices = prices.Where(p => p.MeterType == (int)meterTypeEnum).ToList();
            else
            {
                _logger.Warn("水表类型枚举里不包含当前的水表类型名称");
            }
            return prices;
        }

        /// <summary>
        /// 添加价格信息
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public bool InsertPrice(dynamic obj, string projectId)
        {
           try
            {
                var priceName = obj.title.ToString();
                //var index = obj.index.ToString();
                string meterTypeText = obj.meterType.ToString();
                var tryParse = EnumHelper.TryEnumByDescription(meterTypeText, out MeterType meterTypeEnum);
                if (!tryParse)
                {
                    _logger.Warn("水表类型枚举里不包含当前的水表类型名称");
                    return false;
                }
                var unit = PriceUnit.stere;
                if (obj.unit.ToString() == "元/升")
                    unit = PriceUnit.litre;
                var priceEntity = new PrcieStep()
                {
                    ProjectId = projectId,
                    MeterType = (int)meterTypeEnum,
                    CutPoint1 = Simple.IntConvertString(obj.separation1.ToString()),
                    CutPoint2 = Simple.IntConvertString(obj.separation2.ToString()),
                    PriceUnit = (int)unit,
                    Memo = obj.remark.ToString()
                };
                if (SameName(priceName,priceEntity.Id, projectId))
                    return false;
                using (var _context = new atmk_wmdb_devContext())
                {
                    _context.Add(priceEntity);
                    return _context.SaveChanges() > 0;
                }

            }
            catch (Exception e)
            {
               _logger.Error(e);
                return false;
            }
        }


        public  bool UpdatePrice(dynamic obj)
        {
            try
            {
                var prices = _repository.FindAll<PrcieStep>().Where(p => p.Id.ToString() == obj.id.ToString()).ToList();
                if (!prices.Any())
                {
                    return false;
                }
                var price = prices.First();
                price.Name = obj.title.ToString();
                if (SameName(price.Name,price.Id, price.ProjectId))
                {
                    return false;
                }
                var unit = PriceUnit.stere;
                if (obj.unit.ToString() == "元/升")
                    unit = PriceUnit.litre;
                price.CutPoint1 = Simple.IntConvertString(obj.separation1.ToString());
                price.CutPoint2 = Simple.IntConvertString(obj.separation2.ToString());
                price.PriceUnit = (int)unit;
                price.Memo = obj.remark.ToString();
                //return _repository.Update(price) > 0;
                using (var _context = new atmk_wmdb_devContext())
                {
                    _context.Update(price);
                        return _context.SaveChanges() > 0;
                }
            }
            catch (Exception e)
            {
                _logger.Error(e);
                return false;
            }
        }

        public  bool DeletePrice(string id)
        {
            try
            {
                if (_repository.FindAll<PrcieStep>().Count(r => r.Id.ToString() == id) == 0)
                {
                    _logger.Warn("没有价格信息");
                    return false;
                }
                var price = _repository
                    .FindAll<PrcieStep>().First(r => r.Id.ToString() == id);
                if (_repository.FindAll<PrcieStepFee>().All(s => s.PiceStepId != price.Id.ToString()))
                    return _repository.Remove(price) > 0;
                _logger.Warn("删除失败,有目录下有费用信息");
                return false;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                return false;
            }
        }

        /// <summary>
        /// 添加费用信息
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        public  bool Insertfee(dynamic obj, out Exception exception)
        {
            exception = null;
            try
            {
                var name = obj.title.ToString();
                var index = obj.index.ToString();
                var fees = Enumerable.Where<PrcieStepFee>(_repository.FindAll<PrcieStepFee>(),
                    p => p.PiceStepId == obj.priceId.ToString()).ToList();
                if (fees.Any(r => r.Name == name))
                {
                    exception = new Exception("费用名称重复");
                    return false;
                }
                var feeEntity = new PrcieStepFee(name)
                {
                    PiceStepId = obj.priceId.ToString(), //价格id
                    Price1 = Simple.DoubleConvertString(obj.price1.ToString()), //单价1
                    Price2 = Simple.DoubleConvertString(obj.price2.ToString()), //单价2
                    Price3 = Simple.DoubleConvertString(obj.price3.ToString()), //单价3
                    Memo = obj.remark.ToString() //备注
                };
                if (_repository.Add(feeEntity) > 0)
                    return true;
                exception = new Exception("添加失败");
                return false;
            }
            catch (Exception e)
            {
                exception = e;
                _logger.Error(e);
                return false;
            }
        }

        /// <summary>
        /// 修改费用信息
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        public  bool Updatefee(dynamic obj, out Exception exception)
        {
            try
            {
                exception = null;
                var fees = Enumerable.Where<PrcieStepFee>(_repository.FindAll<PrcieStepFee>(),
                    p => p.Id.ToString() == obj.id.ToString()).ToList();
                if (!fees.Any())
                {
                    exception = new Exception("费用信息不存在，无法修改");
                    return false;
                }
                var fee = fees.First();
                fee.Name = obj.title.ToString();
                fee.PiceStepId = obj.priceId.ToString(); //价格id
                fee.Price1 = Simple.DoubleConvertString(obj.price1.ToString()); //单价1
                fee.Price2 = Simple.DoubleConvertString(obj.price2.ToString()); //单价2
                fee.Price3 = Simple.DoubleConvertString(obj.price3.ToString()); //单价3
                fee.Memo = obj.remark.ToString();
                if (_repository.Update(fee) > 0)
                    return true;
                exception = new Exception("修改失败");
                return false;
            }
            catch (Exception e)
            {
                exception = e;
                _logger.Error(e);
                return false;
            }
        }

        /// <summary>
        /// 删除费用信息
        /// </summary>
        /// <param name="id"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        public  bool Deletefee(string id, out Exception exception)
        {
            try
            {
                exception = null;
                if (Enumerable.Count<PrcieStepFee>(_repository.FindAll<PrcieStepFee>(),
                        r => r.Id.ToString() == id) == 0)
                {
                    exception = new Exception("没有费用信息");
                    return false;
                }
                var price = Enumerable.First<PrcieStepFee>(_repository
                    .FindAll<PrcieStepFee>(), r => r.Id.ToString() == id);

                if (_repository.Remove(price) > 0)
                    return true;
                exception = new Exception("删除失败");
                return false;
            }
            catch (Exception e)
            {
                exception = e;
                _logger.Error(e);
                return false;
            }
        }

        /// <summary>
        /// 是否存在相同的价格名称
        /// </summary>
        /// <param name="priceName"></param>
        /// <param name="priceId"></param>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public bool SameName(string priceName,string priceId, string projectId)
        {
            var prices = PrcieSteps(projectId).Where(p=>p.Id!= priceId);
            return prices.Any(p => p.Name == priceName);
        }
    }
}